package cn.xo68.ide.plugin.common.component;

import cn.xo68.ide.plugin.common.job.ToolSuiteJob;
import cn.xo68.ide.plugin.common.job.ToolSuiteTask;
import cn.xo68.ide.plugin.common.message.TaskListener;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.messages.MessageBus;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * job管理应用级组件
 */
public class ToolSuiteJobManager extends AbstractProjectComponent implements Disposable {

    private ExecutorService executor;
    private MessageBus messageBus;
    private ProgressManager progressManager;

    protected ToolSuiteJobManager(Project project) {
        super(project);
        executor = Executors.newFixedThreadPool(5);
        this.messageBus =project.getMessageBus();
        //ApplicationManager.getApplication().getMessageBus();
        this.progressManager = ProgressManager.getInstance();
    }

    public void submit(ToolSuiteJob toolSuiteJob){
        ToolSuiteTask task=new ToolSuiteTask(this.myProject,toolSuiteJob );
        runInEDT(task);
    }

    private void runInEDT(ToolSuiteTask task) {
        final Application app = ApplicationManager.getApplication();
        // task needs to be submitted in the EDT because progress manager will get the related UI
        if (!app.isDispatchThread()) {
            app.invokeLater(() -> runTask(task));
        } else {
            runTask(task);
        }
    }

    private void runTask(ToolSuiteTask task) {
        if (myProject.isDisposed()) {
            return;
        }
        notifyStart(task.getJob());
        ProgressIndicator progressIndicator = new BackgroundableProcessIndicator(task);
        if (task.isConditionalModal() || task.isModal()) {
            //progressManager.run(task);
            progressManager.runProcess(() -> task.run(progressIndicator), progressIndicator);
        } else {

            executor.submit(() -> progressManager.runProcess(() -> task.run(progressIndicator), progressIndicator));
        }
    }


    @Override
    public void dispose() {
        Disposer.dispose(this);
    }

    private void notifyStart(ToolSuiteJob job) {
        messageBus.syncPublisher(TaskListener.TASK_TOPIC).started(job);
    }
}
